package com.yanqu.road.server.manager.springdinner;

import com.yanqu.road.entity.activity.ActivityConfig;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.springdinner.cross.*;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.logic.bussiness.cross.CrossSpringDinnerBussiness;
import com.yanqu.road.logic.bussiness.servercenter.ActivityBussiness;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.pb.activity.SpringDinnerProto;
import com.yanqu.road.server.logic.MessageHelper;
import com.yanqu.road.server.manager.user.CrossUserMgr;
import com.yanqu.road.message.YanQuMessage;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

public class SpringDinnerActivity {

    private Logger logger = LogManager.getLogger(SpringDinnerActivity.class.getName());

    private SpringDinnerConfig springDinnerConfig;

    //从0开始
    private AtomicInteger tableNo = new AtomicInteger(0);

    private Map<Long, CrossSpringDinnerUserData> userDataMap = new ConcurrentHashMap<>();
    private List<CrossSpringDinnerUserData> needInsertUserDataList = new ArrayList<>();
    private List<CrossSpringDinnerUserData> needUpdateUserDataList = new ArrayList<>();

    //userId 进入时间
    private List<EnterUserIndex> mainSceneUserList = new ArrayList<>();

    //按照用户的桌子 userId no
    private Map<Long,Map<Integer, RedPacketTable>> redPacketTableMap = new ConcurrentHashMap<>();
    //所有桌子 no
    private Map<Integer,RedPacketTable> noRedPacketTableMap = new ConcurrentHashMap<>();
    //还有位置的桌子 no
    private Map<Integer,RedPacketTable> openRedPacketTableMap = new ConcurrentHashMap<>();

    private List<RedPacketTable> needInsertTableList = new ArrayList<>();
    private List<RedPacketTable> needUpdateTableList = new ArrayList<>();

    //开桌同步
    private List<Integer> needSyncOpenTableNoList = new ArrayList<>();
    //同步可以抢
    private Map<Long,Boolean> needSyncCanRobUserMap = new ConcurrentHashMap<>();

    public SpringDinnerActivity(ActivityInfo tmpActivityInfo) {
        // 读配置
        springDinnerConfig = initConfig(tmpActivityInfo);
        // 读数据
        redPacketTableMap = CrossSpringDinnerBussiness.getRedPacketTableMap(tmpActivityInfo.getActivityId());

        for(Map<Integer,RedPacketTable> tables : redPacketTableMap.values()){
            noRedPacketTableMap.putAll(tables);
            for(RedPacketTable table : tables.values()){
                if(table.getStatus() != 1){
                    openRedPacketTableMap.put(table.getNo(),table);
                }
            }
        }

        userDataMap = CrossSpringDinnerBussiness.getUserDataMap(tmpActivityInfo.getActivityId());

        tableNo = new AtomicInteger(CrossSpringDinnerBussiness.getMaxTableIndex(tmpActivityInfo.getActivityId()) + 1);
        remove500outside();
    }

    public ActivityInfo getActivityInfo(){
        return springDinnerConfig.getActivityInfo();
    }

    //移除大于五百张桌子且前面的桌子结束了
    private void remove500outside(){
        int tableCount = noRedPacketTableMap.size();
        if(tableCount > springDinnerConfig.getMaxTableCount()){
            int removeCount = tableCount - springDinnerConfig.getMaxTableCount();
            List<Integer> tableNoList = new ArrayList<>(noRedPacketTableMap.keySet());
            Collections.sort(tableNoList);
            for(int i = 0;i < removeCount ; i++){
                int tableNo = tableNoList.get(i);
                RedPacketTable userTable = noRedPacketTableMap.get(tableNo);
                if(noRedPacketTableMap.get(tableNo).getStatus() == 1){
                    noRedPacketTableMap.remove(tableNo);
                    Map<Integer,RedPacketTable> tableMap = redPacketTableMap.get(userTable.getUserId());
                    synchronized (tableMap){
                        tableMap.remove(tableNo);
                    }
                }else{
                    break;
                }
            }
        }
    }

    private void addNeedSyncOpenTable(int no){
        synchronized (needSyncOpenTableNoList){
            if(!needSyncOpenTableNoList.contains(no)){
                needSyncOpenTableNoList.add(no);
            }
        }
    }

    //保留多少个
    private void clearEnterUser(int count){
        synchronized (mainSceneUserList){
            List<EnterUserIndex> newList = new ArrayList<>();
            mainSceneUserList.sort(new EnterSort());
            for(int i = 0 ; i < count ; i++){
                if(i >= mainSceneUserList.size()){
                    break;
                }
                newList.add(mainSceneUserList.get(i));
            }
            mainSceneUserList = newList;
        }
    }

    private void addEnterUser(long userId){
        synchronized (mainSceneUserList){
            EnterUserIndex selfEnter = null;
            for(EnterUserIndex enterUser : mainSceneUserList){
                if(enterUser.getUserId() == userId){
                    selfEnter = enterUser;
                    break;
                }
            }
            if(selfEnter != null){
                mainSceneUserList.remove(selfEnter);
            }
            EnterUserIndex newEnterUser = new EnterUserIndex();
            newEnterUser.setUserId(userId);
            newEnterUser.setTime(System.currentTimeMillis());
            mainSceneUserList.add(newEnterUser);
        }
    }

    public void timerTask() {
        remove500outside();
        syncOpenTable();
        syncCanRob();
    }

    private void syncCanRob(){
        Map<Long,List<CrossSyncUserData>> syncDataMap = new ConcurrentHashMap<>();
        Map<Long,CrossSpringDinnerUserData> dataMap = new ConcurrentHashMap<>(userDataMap);
        for(CrossSpringDinnerUserData data : dataMap.values()){
            boolean isCanRob = canRandomRob(data.getServerId(),data.getUserId());
            if(!needSyncCanRobUserMap.containsKey(data.getUserId()) || needSyncCanRobUserMap.get(data.getUserId()) != isCanRob){
                if(!syncDataMap.containsKey(data.getServerId())){
                    syncDataMap.put(data.getServerId(),new ArrayList<>());
                }
                needSyncCanRobUserMap.put(data.getUserId(),isCanRob);
                CrossSyncUserData syncUserData = new CrossSyncUserData();
                syncUserData.setServerId(data.getServerId());
                syncUserData.setUserId(data.getUserId());
                syncUserData.setOpenCount(getUserData(data.getServerId(),data.getUserId()).getTableCount());
                syncUserData.setOpenStatusNum(getStatusOpenTableCount(getUserTables(data.getUserId())));
                syncUserData.setCanRob(isCanRob);
                syncDataMap.get(syncUserData.getServerId()).add(syncUserData);
            }
        }
        for(Long serverId : syncDataMap.keySet()){
            List<CrossSyncUserData> syncList = syncDataMap.get(serverId);
            SpringDinnerProto.CrossUserDataSyncMsg.Builder syncMsg = SpringDinnerProto.CrossUserDataSyncMsg.newBuilder();
            syncMsg.setActivityId(springDinnerConfig.getActivityId());
            for(CrossSyncUserData syncUserData : syncList){
                SpringDinnerProto.CrossUserDataTempMsg.Builder syncUserMsg = SpringDinnerProto.CrossUserDataTempMsg.newBuilder();
                syncUserMsg.setUserId(syncUserData.getUserId());
                syncUserMsg.setOpenNum(syncUserData.getOpenStatusNum());
                syncUserMsg.setOpenCount(syncUserData.getOpenCount());
                syncUserMsg.setCanRob(syncUserData.isCanRob());
                syncMsg.addData(syncUserMsg);
            }
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_SPRINGDINNER_CROSS_DATA_ALL_SYNC, syncMsg);
            MessageHelper.sendPacket(serverId, 0, pbMsg);
        }
    }


    //同步刚开的给所有玩家
    private void syncOpenTable(){
        List<Integer> openList = new ArrayList<>();
        if(needSyncOpenTableNoList.size() > 0){
            synchronized (needSyncOpenTableNoList){
                openList = new ArrayList<>(needSyncOpenTableNoList);
                needSyncOpenTableNoList.clear();
            }
        }
        if(openList.size() > 0){
            SpringDinnerProto.SpringDinnerOpenTableSyncMsg.Builder syncMsg = SpringDinnerProto.SpringDinnerOpenTableSyncMsg.newBuilder();
            syncMsg.setActivityId(springDinnerConfig.getActivityId());
            for(Integer no : openList){
                RedPacketTable table = noRedPacketTableMap.get(no);
                SpringDinnerProto.OpenTableTempMsg.Builder tableMsg = parseOpenTableMsg(table);
                if(tableMsg != null){
                    syncMsg.addTable(tableMsg);
                }
            }
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_SPRINGDINNER_RP_TABLE_OPNE_SYNC, syncMsg);
            for(long serverId : springDinnerConfig.getActivityInfo().getServerIdList()){
                MessageHelper.sendPacket(serverId, 0, pbMsg);
            }
        }
    }

    //从大到小按照座位排序
    class EnterSort implements Comparator<EnterUserIndex> {
        @Override
        public int compare(EnterUserIndex o1, EnterUserIndex o2) {
            if (o1.getTime() == o2.getTime()) {
                return 0;
            }
            if (o1.getTime() >= o2.getTime()) {
                return 1;
            }
            return -1;
        }
    }


    private List<EnterUserIndex> getFewSceneUser(long userId){
        List<EnterUserIndex> resUserList = new ArrayList<>();
        int userCount = springDinnerConfig.getRobotUserCount();
        List<EnterUserIndex> enterList = new ArrayList<>(mainSceneUserList);
        int enterCount = enterList.size();
        enterList.sort(new EnterSort());
        for(int i = 1;i <= userCount; i++){
            if(enterCount - i < 0){
                break;
            }
            EnterUserIndex data = enterList.get(enterCount - i);
            if(data.getUserId() == userId){
                userCount++;
                continue;
            }
            resUserList.add(data);
        }
        return resUserList;
    }

    private int getStatusOpenTableCount(Map<Integer,RedPacketTable> tableMap){
        Map<Integer,RedPacketTable> userTableMap = new ConcurrentHashMap<>(tableMap);
        int openCount = 0;
        for(RedPacketTable table : userTableMap.values()){
            if(table.getStatus() == 0){
                openCount++;
            }
        }
        return openCount;
    }

    private boolean canRandomRob(long serverId ,long userId){
        CrossSpringDinnerUserData userData = getUserData(serverId,userId);
        if(userData.getRobCount() >= springDinnerConfig.getLimitRobTimes()){
            return false;
        }
        Map<Integer,RedPacketTable> openTable = new ConcurrentHashMap<>(openRedPacketTableMap);
        for(RedPacketTable table : openTable.values()){
            if(!table.getRobUserMap().containsKey(userId)){
                return true;
            }
        }
        return false;
    }

    public int openTable(long serverId,long userId,long integral,String message){
        SpringDinnerProto.OpenRedPacketTableRespMsg.Builder respMsg = SpringDinnerProto.OpenRedPacketTableRespMsg.newBuilder();
        respMsg.setRet(0);
        CrossSpringDinnerUserData userData = getUserData(serverId,userId);
        Map<Integer, RedPacketTable> tableMap = getUserTables(userId);
        RedPacketTable table = new RedPacketTable();
        synchronized (tableMap){
            long openScoreLimit = springDinnerConfig.getOpenLimitScore(userData.getTableCount()+1);
            if(openScoreLimit > integral){
                return GameErrorCode.E_SPRINGDINNER_RED_OPEN_SCORE_LIMIT;
            }
            if(getStatusOpenTableCount(tableMap) >= springDinnerConfig.getLimitOpenSameTime()){
                return GameErrorCode.E_SPRINGDINNER_RED_OPEN_COUNT_LIMIT;
            }
            table.setActivityId(springDinnerConfig.getActivityId());
            table.setNo(tableNo.getAndIncrement());
            table.setServerId(serverId);
            table.setUserId(userId);
            table.setMessage(message);
            table.setOpenTime(System.currentTimeMillis());
            table.setValue(springDinnerConfig.getRedPacketAllValue());
            table.setRemainValue(springDinnerConfig.getRedPacketAllValue());
            table.setStatus(0);
            table.setUpdateTime(System.currentTimeMillis());
            tableMap.put(table.getNo(),table);
            insertTable(table);
            userData.setTableCount(userData.getTableCount() + 1);
            updateUserData(userData);
            noRedPacketTableMap.put(table.getNo(),table);
            openRedPacketTableMap.put(table.getNo(),table);
            //通知全服玩家
            addNeedSyncOpenTable(table.getNo());
        }
        respMsg.setNo(table.getNo());
        respMsg.setTableNum(tableNo.get());
        Map<Integer,RedPacketTable> page3TableMap = get3PageTableMapByMinOpen(table.getNo());
        for(int tableNo : page3TableMap.keySet()){
            RedPacketTable page3Table = page3TableMap.get(tableNo);
            SpringDinnerProto.TableTempMsg.Builder tableMsg = parseTableMsg(userId,tableNo,page3Table);
            if(tableMsg != null){
                respMsg.addTable(tableMsg);
            }
        }
        //同步给那个玩家自己开了多少有多少在进行中
        syncCrossUserData(serverId,userId);
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_SPRINGDINNER_RP_OPEN, respMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
        return 0;
    }

    public int robTable(long serverId ,int no ,long userId){
        SpringDinnerProto.OpenRedPacketRespMsg.Builder respMsg = SpringDinnerProto.OpenRedPacketRespMsg.newBuilder();
        respMsg.setRet(0);
        if(!noRedPacketTableMap.containsKey(no)){
            return GameErrorCode.E_SPRINGDINNER_RED_TABLE_NOT_EXIT;
        }
        CrossSpringDinnerUserData userData = getUserData(serverId,userId);
        if(userData.getRobCount() >= springDinnerConfig.getLimitRobTimes()){
            return GameErrorCode.E_SPRINGDINNER_RED_TABLE_ROB_MAX;
        }
        RedPacketTable userTable = noRedPacketTableMap.get(no);
        if(userTable.getRobUserMap().containsKey(userId)){
            return GameErrorCode.E_SPRINGDINNER_RED_TABLE_IS_ROB;
        }
        synchronized (userTable){
            if(userTable.getStatus() == 1){
                return GameErrorCode.E_SPRINGDINNER_RED_TABLE_ROB_OVER;
            }
            addRobUserTable(userTable,userId);
            userData.setRobCount(userData.getRobCount() + 1);
            updateUserData(userData);
        }
        respMsg.setValue(userTable.getRobUserMap().get(userId).getValue());
        respMsg.setTable(parseTableMsg(userId,userTable.getNo(),userTable));
        respMsg.setRobNum(userData.getRobCount());
        respMsg.setChangeTime((int)(System.currentTimeMillis()));

        syncRobReward(serverId,userId,respMsg.getValue());
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_SPRINGDINNER_RP_JOIN, respMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
        return 0;
    }

    //随机抢红包随机给一个可以抢的
    private RedPacketTable getRandomCanRobTable(long userId){
        List<Integer> randomList = new ArrayList<>();
        Map<Integer,RedPacketTable> tableMap = new ConcurrentHashMap<>(noRedPacketTableMap);
        for(RedPacketTable table : tableMap.values()){
            if(table.getStatus() != 1){
                if(!table.getRobUserMap().containsKey(userId)){
                    randomList.add(table.getNo());
                }
            }
        }
        if(randomList.size() > 0){
            int index = springDinnerConfig.randomOneTable(0,randomList.size());
            return tableMap.get(randomList.get(index));
        }
        return null;
    }

    private void addRobUserTable(RedPacketTable userTable,long userId){
        RobRedPacketUser robUser = new RobRedPacketUser();
        robUser.setTime(System.currentTimeMillis());
        robUser.setIndex(userTable.getRobUserMap().size() + 1);
        robUser.setUserId(userId);
        int robValue = springDinnerConfig.randomRedPacketValueNew(userTable.getRemainValue(),userTable.getRobUserMap());
        robUser.setValue(robValue);
        userTable.getRobUserMap().put(robUser.getUserId(),robUser);
        userTable.setRemainValue(userTable.getRemainValue() - robValue);
        if(userTable.getRobUserMap().size() >= springDinnerConfig.getRedPacketUserCount()){
            userTable.setStatus(1);
            openRedPacketTableMap.remove(userTable.getNo());
            syncCrossUserData(userTable.getServerId(),userTable.getUserId());
        }
        userTable.setUpdateTime(System.currentTimeMillis());
        updateTable(userTable);
    }

    //随机抢红包
    public int robRandom(long serverId ,long userId){
        SpringDinnerProto.RandomRobRedPacketRespMsg.Builder respMsg = SpringDinnerProto.RandomRobRedPacketRespMsg.newBuilder();
        respMsg.setRet(0);
        RedPacketTable userTable = getRandomCanRobTable(userId);
        if(userTable == null){
            return GameErrorCode.E_SPRINGDINNER_RED_RANDOM_TABLE_NOT_EXIT;
        }
        CrossSpringDinnerUserData userData = getUserData(serverId,userId);
        if(userData.getRobCount() >= springDinnerConfig.getLimitRobTimes()){
            return GameErrorCode.E_SPRINGDINNER_RED_TABLE_ROB_MAX;
        }
        synchronized (userTable){
            if(userTable.getStatus() == 1){
                return GameErrorCode.E_SPRINGDINNER_RED_TABLE_ROB_OVER;
            }
            addRobUserTable(userTable,userId);
            userData.setRobCount(userData.getRobCount() + 1);
            updateUserData(userData);
        }
        respMsg.setValue(userTable.getRobUserMap().get(userId).getValue());
        respMsg.setTable(parseTableMsg(userId,userTable.getNo(),userTable));
        respMsg.setRobNum(userData.getRobCount());

        syncRobReward(serverId,userId,respMsg.getValue());
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_SPRINGDINNER_RP_ROB_RANDOM, respMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
        return 0;
    }

    private void syncRobReward(long serverId, long userId,long rewardValue){
        SpringDinnerProto.CrossTableRobRewardReqMsg.Builder rewardMsg = SpringDinnerProto.CrossTableRobRewardReqMsg.newBuilder();
        rewardMsg.setActivityId(springDinnerConfig.getActivityId());
        rewardMsg.setUserId(userId);
        rewardMsg.setRewardValue(rewardValue);
        YanQuMessage rewardPbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_SPRINGDINNER_RP_ROB_REWARD, rewardMsg);
        MessageHelper.sendPacket(serverId, userId, rewardPbMsg);
    }

    public int robTableMessage(long serverId ,int no ,long userId,String message){
        SpringDinnerProto.RobAddMessageRespMsg.Builder respMsg = SpringDinnerProto.RobAddMessageRespMsg.newBuilder();
        respMsg.setRet(0);
        if(!noRedPacketTableMap.containsKey(no)){
            return GameErrorCode.E_SPRINGDINNER_RED_TABLE_NOT_EXIT;
        }
        RedPacketTable userTable = noRedPacketTableMap.get(no);
        if(!userTable.getRobUserMap().containsKey(userId)){
            return GameErrorCode.E_SPRINGDINNER_RED_TABLE_ROB_NOT_SELF;
        }
        RobRedPacketUser robRedPacketUser = userTable.getRobUserMap().get(userId);
        robRedPacketUser.setMessage(message);
        updateTable(userTable);
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_SPRINGDINNER_RP_ROB_MESSAGE, respMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
        return 0;
    }

    private boolean isSelfJoin(long userId,Map<Long, RobRedPacketUser> joinMap){
        for(RobRedPacketUser robUser : joinMap.values()){
            if(robUser.getUserId() == userId){
                return true;
            }
        }
        return false;
    }

    //获取三页的数据
    private Map<Integer,RedPacketTable> get3PageTableMapByMinOpen(int minOpenTableNo){
        //结束了移除内存了，做标记用，返回给客户端一个通用的数据
        RedPacketTable overTable = new RedPacketTable();
        overTable.setOverTable(true);
        Map<Integer,RedPacketTable> map = new ConcurrentHashMap<>();
        if(minOpenTableNo == -1){
            return map;
        }
        int page = minOpenTableNo/5 + 1;
        int minPage = page;
        int maxPage = page;
        if(page - 1 > 0){
            minPage = page - 1;
        }
        if(noRedPacketTableMap.containsKey(page*5+1)){
            maxPage = page + 1;
        }
        int minNo = (minPage - 1) * 5;
        int maxNo = maxPage * 5 - 1;
        for(int i = minNo;i <= maxNo;i++){
            if(noRedPacketTableMap.containsKey(i)){
                map.put(i,noRedPacketTableMap.get(i));
            }else if(!noRedPacketTableMap.containsKey(i) && i < tableNo.get()){
                map.put(i,overTable);
            }else{
                break;
            }
        }
        return map;
    }

    private Map<Integer,RedPacketTable> get3PageTableMapByPage(Map<Integer,Integer> pageMap){
        //结束了移除内存了，做标记用，返回给客户端一个通用的数据
        RedPacketTable overTable = new RedPacketTable();
        overTable.setOverTable(true);
        Map<Integer,RedPacketTable> map = new ConcurrentHashMap<>();
        for(int page : pageMap.keySet()){
            int pageMinNo = (page - 1) * 5;
            int pageMaxNo = page * 5 - 1;
            for(int i = pageMinNo;i <= pageMaxNo;i++){
                if(noRedPacketTableMap.containsKey(i)){
                    if(noRedPacketTableMap.get(i).getUpdateTime() > (long)pageMap.get(page) * 1000){
                        map.put(i,noRedPacketTableMap.get(i));
                    }
                }else if(!noRedPacketTableMap.containsKey(i) && i < tableNo.get()){
                    map.put(i,overTable);
                }
            }
        }
        return map;
    }

    /**
     *
     * @param userId
     * @param tableNo 过期的移除了table会用同一个对象，这里传一下桌子号
     * @param table
     * @return
     */
    private SpringDinnerProto.TableTempMsg.Builder parseTableMsg(long userId,int tableNo,RedPacketTable table){
        SpringDinnerProto.TableTempMsg.Builder tableMsg = SpringDinnerProto.TableTempMsg.newBuilder();
        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(table.getUserId());
        if(userBaseInfo != null){
            tableMsg.setUserInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
        }
        tableMsg.setNo(tableNo);
        tableMsg.setIsRemove(table.isOverTable());
        if(table.isOverTable()){
            tableMsg.setStatus(1);
        }else{
            tableMsg.setUserId(table.getUserId());
            tableMsg.setMessage(table.getMessage());
            tableMsg.setRobUser(table.getRobUserMap().size());
            tableMsg.setRobValue(table.getValue() - table.getRemainValue());
            tableMsg.setStatus(table.getStatus());
            tableMsg.setIsSelfRob(isSelfJoin(userId,new ConcurrentHashMap<>(table.getRobUserMap())));
        }
        return tableMsg;
    }

    private SpringDinnerProto.OpenTableTempMsg.Builder parseOpenTableMsg(RedPacketTable table){
        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(table.getUserId());
        if(userBaseInfo == null){
            return null;
        }
        SpringDinnerProto.OpenTableTempMsg.Builder tableMsg = SpringDinnerProto.OpenTableTempMsg.newBuilder();
        tableMsg.setNo(table.getNo());
        tableMsg.setOpenTime((int)(table.getOpenTime()/1000));
        tableMsg.setMessage(table.getMessage());
        tableMsg.setUserInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
        tableMsg.setUserId(table.getUserId());
        return tableMsg;
    }

    private SpringDinnerProto.GhostTempMsg.Builder parseGhostMsg(long userId){
        SpringDinnerProto.GhostTempMsg.Builder ghostMsg = SpringDinnerProto.GhostTempMsg.newBuilder();
        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
        if(userBaseInfo == null){
            logger.error(userId + "没有找到基础信息");
            return null;
        }
        ghostMsg.setUserInfo(parsePlayerGhostTempMsg(userBaseInfo));
        return ghostMsg;
    }

    public SpringDinnerProto.PlayerGhostTempMsg.Builder parsePlayerGhostTempMsg(UserBaseInfo enterUserBaseInfo){
        SpringDinnerProto.PlayerGhostTempMsg.Builder msg = SpringDinnerProto.PlayerGhostTempMsg.newBuilder();
        msg.setNickName(enterUserBaseInfo.getNickName());
        msg.setDecoration(enterUserBaseInfo.getDecoration());
        return msg;
    }

    private int getMinCanSeeTableNo(){
        List<Integer> tableNoList = new ArrayList<>(noRedPacketTableMap.keySet());
        if(tableNoList.size() > 0){
            Collections.sort(tableNoList);
            return tableNoList.get(0);
        }
        return 0;
    }

    private int getMaxCanSeeTableNo(){
        List<Integer> tableNoList = new ArrayList<>(noRedPacketTableMap.keySet());
        if(tableNoList.size() > 0){
            Collections.sort(tableNoList);
            Collections.reverse(tableNoList);
            return tableNoList.get(0);
        }
        return 0;
    }

    //获取自己最小的可以抢的桌子
    private int getMiniSelfRobTableNo(long userId){
        List<Integer> tableNoList = new ArrayList<>(openRedPacketTableMap.keySet());
        Collections.sort(tableNoList);
        for(int tableNo : tableNoList){
            RedPacketTable table = openRedPacketTableMap.get(tableNo);
            if(table.getStatus() == 0 && !table.getRobUserMap().containsKey(userId)){
                return tableNo;
            }
        }
        return getMaxCanSeeTableNo();
    }

    public void enterUser(long serverId,long userId,int goNo){
        initUserData(serverId,userId);
        addEnterUser(userId);
        SpringDinnerProto.EnterRedPacketHomeRespMsg.Builder respMsg = SpringDinnerProto.EnterRedPacketHomeRespMsg.newBuilder();
        respMsg.setRet(0);
        int minOpenTableNo = getMiniSelfRobTableNo(userId);
        if(goNo != -1){
            minOpenTableNo = goNo;
        }
        //都没有桌子就是1
        respMsg.setNo(minOpenTableNo);
        Map<Integer,RedPacketTable> userTableMap = get3PageTableMapByMinOpen(minOpenTableNo);
        for(int tableNo : userTableMap.keySet()){
            RedPacketTable table = userTableMap.get(tableNo);
            SpringDinnerProto.TableTempMsg.Builder tableMsg = parseTableMsg(userId,tableNo,table);
            if(tableMsg != null){
                respMsg.addTable(tableMsg);
            }
        }

        List<EnterUserIndex> enterList = getFewSceneUser(userId);
        for(EnterUserIndex user : enterList){
            SpringDinnerProto.GhostTempMsg.Builder enterMsg = parseGhostMsg(user.getUserId());
            if(enterMsg == null){
                continue;
            }
            respMsg.addGhost(enterMsg);
        }

        respMsg.setChangeTime((int)(System.currentTimeMillis()/1000));
        respMsg.setTableNum(tableNo.get());
        respMsg.setRobNum(getUserData(serverId,userId).getRobCount());

        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_SPRINGDINNER_RP_ENTER, respMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
    }

    //形象改了更新一下
    public void changeUserBaseUpdate(long serverId,long userId){
        Map<Integer,RedPacketTable> tableMap = getUserTables(userId);
        for(RedPacketTable table : tableMap.values()){
            table.setUpdateTime(System.currentTimeMillis());
        }
    }

    public void syncCrossUserData(long serverId,long userId){
        SpringDinnerProto.SpringDinnerCrossDataSyncMsg.Builder respMsg = SpringDinnerProto.SpringDinnerCrossDataSyncMsg.newBuilder();
        respMsg.setActivityId(springDinnerConfig.getActivityId());
        respMsg.setOpenHistoryCount(getUserData(serverId,userId).getTableCount());
        respMsg.setOpenStatusNum(getStatusOpenTableCount(getUserTables(userId)));
        boolean canRandomRob = canRandomRob(serverId,userId);
        needSyncCanRobUserMap.put(userId,canRandomRob);
        respMsg.setCanRob(canRandomRob);

        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_SPRINGDINNER_CROSS_DATA_SYNC, respMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
    }

    //获取指定桌子
    public void getTable(long serverId,long userId,Map<Integer,Integer> pageMap,boolean isGetGhost){
        SpringDinnerProto.RedPacketTableRespMsg.Builder respMsg = SpringDinnerProto.RedPacketTableRespMsg.newBuilder();
        respMsg.setActivityId(springDinnerConfig.getActivityId());
        respMsg.setRet(0);
        Map<Integer,RedPacketTable> userTableMap = get3PageTableMapByPage(pageMap);
        for(int tableNo : userTableMap.keySet()){
            RedPacketTable table = userTableMap.get(tableNo);
            SpringDinnerProto.TableTempMsg.Builder tableMsg = parseTableMsg(userId,tableNo,table);
            if(tableMsg != null){
                respMsg.addTable(tableMsg);
            }
        }
        respMsg.setChangeTime((int)(System.currentTimeMillis()/1000));
        for(int page : pageMap.keySet()){
            respMsg.addPageList(page);
        }
        respMsg.setTableNum(tableNo.get());

        if(isGetGhost){
            List<EnterUserIndex> enterList = getFewSceneUser(userId);
            for(EnterUserIndex user : enterList){
                SpringDinnerProto.GhostTempMsg.Builder enterMsg = parseGhostMsg(user.getUserId());
                if(enterMsg == null){
                    continue;
                }
                respMsg.addGhost(enterMsg);
            }
        }

        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_SPRINGDINNER_RP_TABLE, respMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
    }

    private SpringDinnerProto.RobUserTempMsg.Builder parseRobUserPb(RobRedPacketUser robUser){
        SpringDinnerProto.RobUserTempMsg.Builder msg = SpringDinnerProto.RobUserTempMsg.newBuilder();
        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(robUser.getUserId());
        if(userBaseInfo == null){
            logger.error(robUser.getUserId() + "没有找到基础信息");
            return null;
        }
        msg.setServerId(userBaseInfo.getServerId());
        msg.setUserId(robUser.getUserId());
        msg.setNickName(userBaseInfo.getNickName());
        msg.setValue(robUser.getValue());
        return msg;
    }

    public int tableRobUserList(long serverId,int no,long userId){
        SpringDinnerProto.RedPacketTableRobUserRespMsg.Builder respMsg = SpringDinnerProto.RedPacketTableRobUserRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setNo(no);
        respMsg.setActivityId(springDinnerConfig.getActivityId());
        if(!noRedPacketTableMap.containsKey(no)){
            return GameErrorCode.E_SPRINGDINNER_RED_TABLE_NOT_EXIT;
        }
        RedPacketTable table = noRedPacketTableMap.get(no);
        respMsg.setTable(parseTableMsg(userId,table.getNo(),table));

        List<RobRedPacketUser> robList = new ArrayList<>(table.getRobUserMap().values());
        Map<Integer,RobRedPacketUser> robRedPacketUserMap = new ConcurrentHashMap<>();
        for(RobRedPacketUser robUser : robList){
            robRedPacketUserMap.put(robUser.getIndex(),robUser);
        }
        for(int i = robRedPacketUserMap.size(); i > 0 ; i--){
            RobRedPacketUser robUser = robRedPacketUserMap.get(i);
            SpringDinnerProto.RobUserTempMsg.Builder robUserTempMsg = parseRobUserPb(robUser);
            if(robUserTempMsg == null){
                continue;
            }
            respMsg.addRobUser(robUserTempMsg);
        }

        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_SPRINGDINNER_RP_ROB_USER, respMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
        return 0;
    }


    private CrossSpringDinnerUserData getUserData(long serverId,long userId){
        if(!userDataMap.containsKey(userId)){
            initUserData(serverId,userId);
        }
        return userDataMap.get(userId);
    }

    private Map<Integer,RedPacketTable> getUserTables(long userId){
        if(!redPacketTableMap.containsKey(userId)){
            redPacketTableMap.put(userId,new ConcurrentHashMap<>());
        }
        return redPacketTableMap.get(userId);
    }

    private void initUserData(long serverId,long userId){
        if(userDataMap.containsKey(userId)){
            return;
        }
        CrossSpringDinnerUserData data = new CrossSpringDinnerUserData();
        data.setActivityId(springDinnerConfig.getActivityId());
        data.setServerId(serverId);
        data.setUserId(userId);
        data.setTableCount(0);
        data.setUpdateTime(System.currentTimeMillis());
        synchronized (userDataMap){
            userDataMap.put(userId,data);
        }
        insertUserData(data);
    }

    private void insertTable(RedPacketTable table){
        synchronized (needInsertTableList){
            needInsertTableList.add(table);
        }
    }

    private void updateTable(RedPacketTable table){
        synchronized (needUpdateTableList){
            if (!needUpdateTableList.contains(table)) {
                needUpdateTableList.add(table);
            }
        }
    }

    private void insertUserData(CrossSpringDinnerUserData data){
        synchronized (needInsertUserDataList){
            needInsertUserDataList.add(data);
        }
    }

    private void updateUserData(CrossSpringDinnerUserData table){
        synchronized (needUpdateUserDataList){
            if (!needUpdateUserDataList.contains(table)) {
                needUpdateUserDataList.add(table);
            }
        }
    }

    public void save() {
        clearEnterUser(springDinnerConfig.getRobotUserCount());

        List<RedPacketTable> tempInsertList;
        synchronized (needInsertTableList) {
            tempInsertList = new ArrayList<>(needInsertTableList);
            needInsertTableList.clear();
        }
        if (tempInsertList.size() > 0) {
            CrossSpringDinnerBussiness.addRedPacketTableList(tempInsertList);
        }
        List<RedPacketTable> tempUpdateList;
        synchronized (needUpdateTableList) {
            tempUpdateList = new ArrayList<>(needUpdateTableList);
            needUpdateTableList.clear();
        }
        if (tempUpdateList.size() > 0) {
            CrossSpringDinnerBussiness.updateRedPacketTableList(tempUpdateList);
        }

        List<CrossSpringDinnerUserData> tempUserInsertList;
        synchronized (needInsertUserDataList) {
            tempUserInsertList = new ArrayList<>(needInsertUserDataList);
            needInsertUserDataList.clear();
        }
        if (tempUserInsertList.size() > 0) {
            CrossSpringDinnerBussiness.addUserDataList(tempUserInsertList);
        }


        List<CrossSpringDinnerUserData> tempUserUpdateList;
        synchronized (needUpdateUserDataList) {
            tempUserUpdateList = new ArrayList<>(needUpdateUserDataList);
            needUpdateUserDataList.clear();
        }
        if (tempUserUpdateList.size() > 0) {
            CrossSpringDinnerBussiness.updateUserDataList(tempUserUpdateList);
        }
    }

    /**
     * 生成一份配置
     */
    private SpringDinnerConfig initConfig(ActivityInfo tmpActivityInfo) {
        SpringDinnerConfig tmpConfig = new SpringDinnerConfig();
        tmpConfig.setActivityInfo(tmpActivityInfo);
        tmpConfig.setActivityId(tmpActivityInfo.getActivityId());

        List<Integer> activityIdList = new ArrayList<>();
        activityIdList.add(tmpActivityInfo.getActivityId());

        // 其他配置
        Map<String, ActivityConfig> activityConfigMap = ActivityBussiness.getActivityConfigMap(activityIdList).get(tmpActivityInfo.getActivityId());

        tmpConfig.initOpenLimit(activityConfigMap.get("SPRING_DINNER_OPEN_LIMIT").getValue());
        tmpConfig.initRedPacket(activityConfigMap.get("SPRING_DINNER_RED_BAG_PARAM").getValue());
        tmpConfig.initRobotUserCount(activityConfigMap.get("SPRING_DINNER_ROBOT_USER_COUNT").getIntValue());
        if(activityConfigMap.containsKey("SPRING_DINNER_MAX_TABLE_COUNT")){
            tmpConfig.initMaxTableCount(activityConfigMap.get("SPRING_DINNER_MAX_TABLE_COUNT").getIntValue());
        }
        return tmpConfig;
    }

    /**
     * 重新加载配置
     */
    public void reloadConfig() {
        int activityId = springDinnerConfig.getActivityId();
        ActivityInfo activityInfo = ActivityBussiness.getActivityInfoByActivityId(activityId);
        springDinnerConfig = initConfig(activityInfo);
    }

    /**
     * 热更
     */
    public void repair() {

    }
}
